package org.rbac.web.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.json.JSONObject;
import org.rbac.content.RbacApplicationContent;
import org.rbac.content.define.RbacKeyDefine;
import org.rbac.content.define.RbacKeyDefine.keys;
import org.rbac.vo.Action;
import org.rbac.vo.User;
import org.rbac.web.filter.logicFilter.GridFilter;
import org.rbac.web.filter.logicFilter.TreeFilter;

import com.kingschan.easyquery.logic.SuffixFilter;
import com.kingschan.lang.StringUtil;
import com.kingschan.regx.RegexUtil;
import com.kingschan.web.ServletUtil;
/**
 * 
*  <pre>    
* 类名称：RbacCoreFilter 
* 类描述：   
* 创建人：陈国祥   (kingschan)
* 创建时间：2015-4-2 下午4:00:08   
* 修改人：Administrator   
* 修改时间：2015-4-2 下午4:00:08   
* 修改备注：   
* @version V1.0
* </pre>
 */
public class RbacCoreFilter  implements Filter{
    
    private Map<String, Object> current_request_params=null;//当前请求参数
    private long beginTime=0;
    private final String endsuffix_regx="\\.[a-z]+$";
    private String project_name;//部署目录名字
    private String current_action;//当前请求的action名字
    private String endsuffix;//后缀
    private Boolean pass;//是否有权限通过  默认为false
    private String ip;
    private String method;
    private Integer uid;
    private RbacApplicationContent content;
    
    //configure
    private String admins;//当前系统管理员集合，已;分隔
    private String pageHome;//根目录跳转地址
    private String pageLogin;//登录地址
    private String pageWithoutPrivilege;//无权限访问页面
    private String staticSuffix;//静态资源后缀直接通过
    
    
    
    public RbacApplicationContent getContent() {
        return content;
    }

    public void setContent(RbacApplicationContent content) {
        this.content = content;
    }
    
    public String getAdmins() {
        return admins;
    }

    public void setAdmins(String admins) {
        this.admins = admins;
    }

    public String getPageHome() {
        return pageHome;
    }

    public void setPageHome(String pageHome) {
        this.pageHome = pageHome;
    }

    public String getPageLogin() {
        return pageLogin;
    }

    public void setPageLogin(String pageLogin) {
        this.pageLogin = pageLogin;
    }

    public String getPageWithoutPrivilege() {
        return pageWithoutPrivilege;
    }

    public void setPageWithoutPrivilege(String pageWithoutPrivilege) {
        this.pageWithoutPrivilege = pageWithoutPrivilege;
    }

    public String getStaticSuffix() {
        return staticSuffix;
    }

    public void setStaticSuffix(String staticSuffix) {
        this.staticSuffix = staticSuffix;
    }





    /**
     * 后缀名处理器映射
     */
    private static Map<String, SuffixFilter> suffix;
    private static Logger log = Logger.getLogger(RbacCoreFilter.class);
    
    static{
        suffix= new HashMap<String, SuffixFilter>();
        suffix.put(".grid", new GridFilter());
        suffix.put(".tree", new TreeFilter());
    }
    
    @Override
    public void destroy() {
        
    }

    @Override
    public void doFilter(ServletRequest sreq, ServletResponse srep, FilterChain fc)throws IOException, ServletException {
        pass=false;
        uid=-1;
        HttpServletRequest request=(HttpServletRequest) sreq;
        HttpServletResponse response=(HttpServletResponse) srep;
        current_request_params=ServletUtil.getParameterMap(request);
        beginTime=System.currentTimeMillis();
        endsuffix=RegexUtil.findStrByRegx(request.getRequestURI(), endsuffix_regx);//得到后缀
        ip=content.getClientIP(request);
        method=request.getMethod();        
        sreq.setCharacterEncoding("UTF-8");     
        project_name=request.getContextPath();//项目名
        current_action=request.getRequestURI().replaceFirst(String.format("%s/", project_name), "").replaceAll("^/", "");
        current_action=current_action.indexOf(";jsessionid")!=-1?current_action.replaceFirst("\\;jsessionid=\\w{32}", ""):current_action;
        current_action=current_action.isEmpty()?"/":current_action;
        
        Action a = null;
        if (request.getRequestURI().matches(".*\\.[png|jpg|js|css|gif|eto|svg|ttf|woff|woff2]+$")) {
            fc.doFilter(request, response);
           // log.debug("静态资源直接通过："+current_action);
            return;
        }
        else if(request.getRequestURI().matches(".*\\.[grid|tree]+$")){
            log.debug("【临时使用】直接通过："+current_action);
            try {
                passRequest(request, response,fc);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return ;
        }else if (current_action.equals("/")) {
            request.getRequestDispatcher(getPageHome()).forward(request, response);
            return;
        }
       try {        
                a=content.getActionByUrl(current_action);
               if (null==a) {
                   log.info("未配置资源:"+current_action);
                   pass=true;
               }else if (0==a.getAControl()) {
                   //false 是白名单
                   pass=true;
               }else{
                   User user =(User) request.getSession().getAttribute(RbacKeyDefine.getKey(keys.CURRENT_USER));
                   if (null==user) {
                       response.sendRedirect(String.format("%s/%s", project_name,getPageLogin()));
                   }else{//已经登录
                       uid=user.getId();
                       if (2==a.getAControl()||user.getAdmin()) {
                         //登录可见  或者当成用户是管理员
                           setAccessBtn( request, current_action);
                           pass=true;
                       }else if (null!=content.getUserAccessAction(request).get(current_action)) {
                           setAccessBtn( request, current_action);
                           pass=true;
                       }
                   }
               } 
               if (pass) {
                   passRequest(request, response,fc);
               }else{
                   //没权限访问
                   request.getRequestDispatcher(getPageWithoutPrivilege()).forward(request, response);
                   return;
               }
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                long end_seconds=System.currentTimeMillis()-beginTime;
                if (null!=a) {
                    if (a.getALoging()) {
                        JSONObject json =new JSONObject(current_request_params);
                         content.log(ip, method, current_action, uid,
                            json.length()>0?json.toString():"" ,
                            a.getAName(), pass, end_seconds,
                            StringUtil.null2Empty(request.getHeader("Referer")));
                    }else{
                       /* System.out.println("---------------------------------------------------------------------");
                        System.out.println("Action:"+current_action);
                        System.out.println("所属资源:"+a.getAName());
                        System.out.println("是否记录日志："+a.getALoging());
                        System.out.println("是否通过："+pass);
                        System.out.println("后缀："+endsuffix);
                        System.out.println("参数："+current_request_params);
                        System.out.println(String.format("处理耗时:%d 毫秒", end_seconds));*/
                    }
                }
            }
       
    }

    void passRequest(HttpServletRequest request,HttpServletResponse response,FilterChain fc) throws Exception{
        String action=current_action.replaceAll(endsuffix_regx, "");
        if (!endsuffix.isEmpty()&&suffix.containsKey(endsuffix)) {
            current_request_params.put("$action", action);
            current_request_params.put("Current_User", request.getSession().getAttribute("Current_User"));
            suffix.get(endsuffix).doFilter(request, response, current_request_params);
        }else {
            fc.doFilter(request, response);
        }
    }
    
    
    @Override
    public void init(FilterConfig fc) throws ServletException {
        this.pass=false;
        
    }

    /**
     * 设置可访问的按扭
     * @param req
     * @param actionName
     * @throws Exception 
     */
    void setAccessBtn(HttpServletRequest req,String actionName) throws Exception{
        List<Object> btns=content.getCurrentPageBtns(req, actionName);
        if (null!=btns&&btns.size()>0) {
            for (int i = 0; i < btns.size(); i++) {
                @SuppressWarnings("unchecked")
                Map<String, Object> map =(Map<String, Object>) btns.get(i);
                String template="<a  href=\"javascript:void(0);\" class=\"easyui-linkbutton\" plain=\"true\" iconCls=\"%s\"  onclick=\"%s\">%s</a>";
                String html=String.format(template, map.get("a_icon"),map.get("a_href"),map.get("a_name"));
                System.out.println(html);
                req.setAttribute(map.get("a_name").toString(), html);
            }
            
        }
    }
    
    void outPrintMsg(HttpServletResponse response,String msg){
       try {
           response.setContentType(String.format("text/html;charSet=%s", "UTF-8"));
           PrintWriter pw = response.getWriter();
           pw.print(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
   @PostConstruct
    void initTest(){
        System.out.println(this.getClass().getName()+"初始化了！");
    }
    
    @PreDestroy
    void releaseTest(){
        System.out.println(this.getClass().getName()+"销毁了！");
    }
    
    
}
